package com.hk.blog.controller;

import com.hk.blog.domain.ArticleInfo;
import com.hk.blog.service.ArticleInfoService;
import com.hk.blog.service.CategoryInfoService;
import com.hk.blog.vo.ArticleSearchBean;
import com.hk.commons.JsonResult;
import com.hk.commons.query.Order;
import com.hk.commons.query.QueryModel;
import com.hk.commons.util.ObjectUtils;
import com.hk.core.authentication.api.SecurityContextUtils;
import com.hk.core.service.exception.ServiceException;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author Kevin
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("article")
public class ArticleInfoController {

    private final ArticleInfoService articleInfoService;

    private final CategoryInfoService categoryInfoService;

    @GetMapping(path = "/get")
    public JsonResult<?> get(@RequestParam(required = false) Long id) {
        Map<String, Object> result = new HashMap<>(2);
        if (Objects.nonNull(id)) {
            var articleInfo = articleInfoService.findById(id)
                    .map(item -> {
                        if (item.getProtect() && !SecurityContextUtils.isAuthenticated()) {
                            throw new ServiceException(JsonResult.unauthorized("请先登陆再查看文章内容"));
                        }
                        item.setBrowseNum(ObjectUtils.defaultIfNull(item.getBrowseNum(), 0) + 1);
                        return articleInfoService.updateById(item);
                    }).orElse(null);
            result.put("article", articleInfo);
        }
        result.put("categoryList", categoryInfoService.findByUserId(
                        SecurityContextUtils.getPrincipal().getUserId(), Order.desc("lastModifiedDate"))
                .stream()
                .map(item -> Map.of("value", Objects.requireNonNull(item.getId()),
                        "label", item.getCategoryName()))
                .collect(Collectors.toList()));
        return JsonResult.success(result);
    }

    @GetMapping(path = "/detail/{id}")
    public JsonResult<?> detail(@PathVariable Long id) {
        var articleInfo = articleInfoService.findById(id)
                .map(item -> {
                    if (item.getProtect() && !SecurityContextUtils.isAuthenticated()) {
                        throw new ServiceException(JsonResult.unauthorized("请先登陆再查看文章内容"));
                    }
                    item.setBrowseNum(ObjectUtils.defaultIfNull(item.getBrowseNum(), 0) + 1);
                    return articleInfoService.updateById(item);
                })
                .map(item -> Map.of("id", id, "title", item.getTitle(),
                        "content", item.getContent()))
                .orElse(null);
        return JsonResult.success(articleInfo);
    }

    /**
     * 批量查询文章数据
     */
    @PostMapping(path = "/batch/get")
    public JsonResult<?> get(@Validated @RequestBody List<BatchSearchBean> batchSearchBeans) {
        List<Map<String, Object>> result = new ArrayList<>(batchSearchBeans.size());
        var ids = batchSearchBeans.stream().map(BatchSearchBean::getId).collect(Collectors.toSet());
        var articleInfoList = articleInfoService.findByIds(ids);
        for (BatchSearchBean item : batchSearchBeans) {
            var article = articleInfoList.stream()
                    .filter(articleInfo -> Objects.equals(articleInfo.getId(), item.getId()))
                    .findFirst()
                    .orElse(null);
            Map<String, Object> map = (article == null) ? Map.of("requestId", item.getRequestId()) :
                    Map.of("requestId", item.getRequestId(), "order", article);
            result.add(map);
        }
        return JsonResult.success(result);
    }

    @Data
    private static class BatchSearchBean implements Serializable {

        @NotNull
        private Long id;

        @NotEmpty
        private String requestId;
    }

    @PostMapping(path = "delete")
    public JsonResult<Boolean> deleteById(@RequestParam Long id) {
        articleInfoService.deleteById(id);
        return JsonResult.success(true);
    }

    @PostMapping(path = "page")
    public JsonResult<?> findPage(@RequestBody QueryModel<ArticleSearchBean> queryModel) {
        queryModel.getParam().setUserId(SecurityContextUtils.getPrincipal().getUserId());
        return JsonResult.success(articleInfoService.findForPage(queryModel));
    }

    @PostMapping(path = "save")
    public JsonResult<?> saveOrUpdate(@RequestBody ArticleInfo articleInfo) {
        articleInfo.setUserId(SecurityContextUtils.getPrincipal().getUserId());
        articleInfoService.insertOrUpdate(articleInfo);
        return JsonResult.success(true);
    }
}
